﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace Lon.IO
{
    public  class FixLenFile
    {
        UInt32 ver = 0;
        byte[] recState;
        bool IsOpen;
        String fileName;
        byte cacheState;
        long dataOffset;
        uint cyclePoint;
        int recLen;
        

        public String FileName
        {
            get { return fileName; }
            set { fileName = value; }
        }
        public FixLenFile(string fileName)
        {
            this.fileName = fileName;
            this.Load();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <param name="recLen">单条记录长度</param>
        /// <param name="recCount">记录数量</param>
        public FixLenFile(String fileName,int recLen,int recCount)
        {
            this.fileName = fileName;
            this.recLen = recLen;
            this.recState = new byte[recCount];
            this.ver=1;
            for(int i=0;i<recState.Length;i++)
            {
                this.recState[i] = 0;
            }
            this.dataOffset = 512 + this.recState.Length;
            Save();
            this.IsOpen = true;
          
        }

        private void Save()
        {
            try
            {
                using (FileStream fs = new FileStream(this.fileName, FileMode.OpenOrCreate))
                {
                    BinaryWriter br = new BinaryWriter(fs);
                    WriteVer(br);
                    WriteCacheState(br);
                    WriteRecCount(br);
                    WriteRecLen(br);
                    WriteCyclePoint(br);
                    br.Seek((int)(this.dataOffset + this.recLen * recState.Length), SeekOrigin.Begin);
                    br.Write("文件到这里结束");
                    br.Close();
                    fs.Close();
                }
              
            }
            catch (System.Exception ex)
            {

            }
        }

        private void WriteCyclePoint(BinaryWriter br)
        {
            br.Write(cyclePoint); 
        }

        private void WriteVer(BinaryWriter br)
        {
            br.Write(0x00000001);
        }

        private void WriteCacheState(BinaryWriter br)
        {
            br.Write((byte)0x00);
        }

        private void WriteRecCount(BinaryWriter br)
        {
            br.Write(this.recState.Length);
        }

        private void WriteRecLen(BinaryWriter br)
        {
            br.Write(this.recLen); 
        }
        /// <summary>
        ///  返回错误代码
        /// </summary>
        /// <returns></returns>
        public int Load()
        {
            if (String.IsNullOrEmpty(fileName))
            {
                return 1;
            }
            if (!File.Exists(fileName))
            {
                return 2;
            }
            try
            {
                using (FileStream fs = File.OpenRead(fileName))
                {
                    BinaryReader br = new BinaryReader(fs);
                    ReadVer(br);
                    ReadCacheState(br);
                    ReadRecCount(br);
                    ReadRecLen(br);
                    ReadCyclePoint(br);
                    ReadRecState(br);
                    br.Close();
                    fs.Close();
                }
                this.IsOpen=true;
                return 0;
            }
            catch (System.Exception ex)
            {
                return 3;
            }
        }

        private void ReadCyclePoint(BinaryReader br)
        {
            this.cyclePoint = br.ReadUInt32();
            
        }
        public byte[] ReadRec(UInt32 index)
        {
            if (!this.IsOpen)
            {
                return new byte[0];
            }
            if (String.IsNullOrEmpty(fileName))
            {
                return new byte[0];
            }
            if (!File.Exists(fileName))
            {
                return new byte[0];
            }
            index = (UInt32)(index % recState.Length);
            try
            {
                byte[] ret = new byte[0];
                using (FileStream fs = File.OpenRead(fileName))
                {
                    BinaryReader br = new BinaryReader(fs);
                    fs.Seek(this.dataOffset + this.recLen * index,SeekOrigin.Begin);
                    ret = br.ReadBytes(recLen);
                    br.Close();
                    fs.Close();
                }
                return ret;

            }
            catch
            {
                return null;
            }
        }

        private void ReadVer(BinaryReader br)
        {
            this.ver = br.ReadUInt32();
        }

        private void ReadCacheState(BinaryReader br)
        {
            this.cacheState = br.ReadByte();
        }

        private void ReadRecCount(BinaryReader br)
        {
            UInt32 recCount = br.ReadUInt32();
            this.recState = new byte[recCount];
           
        }

        private void ReadRecLen(BinaryReader br)
        {
            this.recLen = br.ReadInt32();
            this.dataOffset = this.recState.Length +512;

        }

        private void ReadRecState(BinaryReader br)
        {
            br.BaseStream.Seek(512, SeekOrigin.Begin);
            for (int i = 0; i < this.recState.Length; i++)
            {
                this.recState[i] = br.ReadByte();
            }
            
        }

        /// <summary>
        /// 返回写的头条记录
        /// </summary>
        /// <param name="vals"></param>
        /// <returns></returns>
        public UInt32 CycleWrite(byte[] vals)
        {
            UInt32 ret = cyclePoint;
            //WriteRec(cyclePoint, vals);
            UInt32 writedRecCount = (UInt32)Math.Ceiling(((double)vals.Length) / recLen);
            for(int i=0;i<writedRecCount;i++)
            {
                cyclePoint++;
                cyclePoint = (UInt32)(cyclePoint % this.recState.Length);
                recState[cyclePoint] = 0x01;
            }
            WriteRec(ret, vals);
            //this.Save();
            return ret;
            
            
        }


        private void WriteRec(uint index, byte[] vals)
        {
            try
            {
                using (FileStream fs = new FileStream(this.fileName, FileMode.OpenOrCreate))
                {
                    BinaryWriter bw = new BinaryWriter(fs);
                    WriteVer(bw);
                    WriteCacheState(bw);
                    WriteRecCount(bw);
                    WriteRecLen(bw);
                    WriteCyclePoint(bw);
                    WriteRecState(bw);
                    bw.Seek((int)(this.dataOffset + index * recLen), SeekOrigin.Begin);
                    bw.Write(vals);
                    bw.Seek((int)(this.dataOffset + this.recLen * recState.Length), SeekOrigin.Begin);
                  
                    bw.Write("文件到这里结束");
                    bw.Close();
                    fs.Close();
                }
            }
            catch (System.Exception ex)
            {

            }
        }

        private void WriteRecState(BinaryWriter bw)
        {
            bw.BaseStream.Seek(512, SeekOrigin.Begin);
            bw.Write(this.recState);
            
        }



        public void Close()
        {
            this.recState = null;
            this.IsOpen = false;
        }
    }
}
